package logic

import (
	"errors"
	"fmt"
	"github.com/gogf/gf/encoding/gjson"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/os/glog"
	"github.com/gogf/gf/text/gstr"
	"websocket/app/service/websocket/logic/common"
	"websocket/app/service/websocket/logic/sys"
	"websocket/app/service/websocket/logic/wpp"
)

var logic = map[string]map[string]func(ctx *common.WorkContext) (g.Map, error){
	"sys": {
		"ping":  sys.Ping,
		"go":    sys.Go,
		"sync":  sys.Sync,
		"point": sys.Point,
	},
	"wpp": {
		"ping":  wpp.Ping,
		"go":    wpp.Go,
		"sync":  wpp.Sync,
		"point": wpp.Point,
		"my":    wpp.My,
		"test2": wpp.Test2,
	},
}

func Call(unique interface{}, data *gjson.Json) g.Map {
	cmd := data.GetString("cmd", "")
	context := &common.WorkContext{
		Data: common.Medium{
			Cmd:      cmd,
			Unique:   unique,
			Original: data,
		},
	}
	var callBack g.Map
	if gstr.Contains(cmd, ".") {
		command := gstr.Explode(".", cmd)
		back := g.Map{}
		for _, cmd := range command[1:] {
			call, err := callFunc(command[0], cmd, context)
			if err != nil {
				glog.Print(command[0] + "." + cmd + " error:" + err.Error())
				back[command[0]+"."+cmd] = g.Map{
					"error": err.Error(),
				}
			} else {
				back[command[0]+"."+cmd] = call
			}
		}
		callBack = back
	} else {
		callBack = callAllFunc(cmd, context)
	}
	return callBack
}

func callFunc(alias, method string, context *common.WorkContext) (data g.Map, err error) {
	defer func() {
		if e := recover(); e != nil {
			err = errors.New(fmt.Sprintf(`%v`, e))
			runRecover(err)
		}
		return
	}()
	data, err = logic[alias][method](context)
	return
}

func callAllFunc(alias string, context *common.WorkContext) g.Map {
	back := g.Map{}
	for method, _ := range logic[alias] {
		call, err := callFunc(alias, method, context)
		if err != nil {
			glog.Print(alias + "." + method + " error:" + err.Error())
			back[alias+"."+method] = g.Map{
				"error": err.Error(),
			}
		} else {
			back[alias+"."+method] = call
		}
	}
	return back
}

func runRecover(err error) {
	g.Log().Cat("logic").Error(err)
}
